﻿using Microsoft.Extensions.Configuration;
using System.Collections.Concurrent;
using System.Data;
using System.Threading.Tasks;
using SZORM.Core;
using SZORM.Descriptors;
using SZORM.Factory;
using SZORM.Infrastructure;
using SZORM.Infrastructure.Interception;
using SZORM.Query;
using SZORM.Query.Internals;
using SZORM.Utility;
using SZORM.Utility.SnowId;

namespace SZORM
{
    /// <summary>
    /// 数据库上下文核心类，负责数据访问层的会话管理、事务控制和查询执行
    /// </summary>
    /// <remarks>
    /// 提供对数据库的统一访问入口，封装了连接管理、事务处理和数据操作方法。
    /// 支持同步和异步操作，通过泛型方法提供类型安全的查询能力。
    /// </remarks>
    public abstract partial class DbContext : IDbContext, IDisposable, IAsyncDisposable
    {
        /// <summary>
        /// 指示当前实例是否已释放
        /// </summary>
        private bool _disposed;

        /// <summary>
        /// 内部ADO会话实例，负责数据库连接和命令执行的底层管理
        /// </summary>
        internal InternalAdoSession _internalAdoSession;

        /// <summary>
        /// 数据库结构检查器，用于验证数据库架构一致性
        /// </summary>
        private IStructure _dbStructCheck;

        /// <summary>
        /// 实体类型描述符缓存，存储已解析的实体元数据
        /// </summary>
        internal ConcurrentDictionary<Type, TypeDescriptor> _typeDescriptors;


        /// <summary>
        /// 默认事务隔离级别
        /// </summary>
        private IsolationLevel _il;

        /// <summary>
        /// 数据库提供程序，适配不同数据库类型的操作
        /// </summary>
        internal IDatabaseProvider _dbDatabaseProvider;


        /// <summary>
        /// 数据库连接字符串
        /// </summary>
        internal string _dbConnectionStr;


        /// <summary>
        /// 数据库类型标识（如SQLServer、MySQL等）
        /// </summary>
        internal string _dbType;

        /// <summary>
        /// 是否为只读查询模式
        /// </summary>
        /// <summary>
        /// 指示当前上下文是否为只读查询模式
        /// </summary>
        private readonly bool isSelect;
        /// <summary>
        /// 默认打开事物处理
        /// </summary>
        /// <summary>
        /// 初始化DbContext实例并指定事务隔离级别
        /// </summary>
        /// <param name="il">事务隔离级别，默认为ReadCommitted</param>
        public DbContext(IsolationLevel il = IsolationLevel.ReadCommitted)
        {
            Type type = GetType();
            DbContextInit(type.Name, il);
        }
        /// <summary>
        /// 初始化DbContext实例并指定上下文名称和事务隔离级别
        /// </summary>
        /// <param name="dbContextName">数据库上下文配置名称</param>
        /// <param name="il">事务隔离级别，默认为ReadCommitted</param>
        public DbContext(string dbContextName, IsolationLevel il = IsolationLevel.ReadCommitted)
        {
            DbContextInit(dbContextName, il);
        }
        /// <inheritdoc/>
        public DbContext(bool _isSelect, IsolationLevel il = IsolationLevel.ReadCommitted)
        {
            isSelect = _isSelect;
            Type type = GetType();
            DbContextInit(type.Name, il);
        }
        /// <summary>
        /// 初始化数据库上下文配置，包括读取配置文件、设置缓存和初始化雪花ID生成器
        /// </summary>
        /// <param name="dbContextName">数据库上下文配置名称</param>
        /// <param name="il">事务隔离级别，默认为ReadCommitted</param>
        public void DbContextInit(string dbContextName, IsolationLevel il = IsolationLevel.ReadCommitted)
        {
            //获取名字
            object isHave = Cache.GetOrAdd(dbContextName, key =>
            {
                ConfigurationBuilder builder = new ConfigurationBuilder();
                string path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
                Console.WriteLine("数据库上下文初始化基础路径: " + path);

                string szormPath = Path.Combine(path, "szorm.json");
                string appSettingPath = Path.Combine(path, "appsettings.json");
                Console.WriteLine("数据库配置文件路径1: " + szormPath);
                Console.WriteLine("数据库配置文件路径2: " + appSettingPath);
                if (!File.Exists(szormPath) && !File.Exists(appSettingPath))
                {
                    throw new Exception("没有配置文件,可以选择\"szorm.json\"或者\"appsettings.json\"");
                }
                if (File.Exists(szormPath))
                {
                    _ = builder.AddJsonFile(szormPath);
                }

                if (File.Exists(appSettingPath))
                {
                    _ = builder.AddJsonFile(appSettingPath);
                }

                IConfigurationRoot configuration = builder.Build();

                string tmpType = configuration[dbContextName + ":type"];
                if (string.IsNullOrEmpty(tmpType))
                {
                    throw new Exception("未配置" + dbContextName + "类型type");
                }
                string tmpConnStr = configuration[dbContextName + ":connStr"];
                if (string.IsNullOrEmpty(tmpConnStr))
                {
                    throw new Exception("未配置" + dbContextName + "类型connStr");
                }

                Cache.Add(dbContextName + ":type", configuration[dbContextName + ":type"]);
                Cache.Add(dbContextName + ":connStr", configuration[dbContextName + ":connStr"]);
                Cache.Add(dbContextName + ":workerId", configuration[dbContextName + ":workerId"] ?? "1");
                string WorkerId = Cache.Get(dbContextName + ":workerId").ToString();
                //初始化雪花id
                SnowIdHelper.SetIdGenerator(new Utility.SnowId.Contract.IdGeneratorOptions() { WorkerId = ushort.Parse(WorkerId) });
                return "1";
            });

            _dbType = Cache.Get(dbContextName + ":type").ToString();
            _dbConnectionStr = Cache.Get(dbContextName + ":connStr").ToString();
            Init(il);
        }
        /// <summary>
        /// 初始化数据库上下文核心组件，包括数据库提供程序、连接工厂和事务设置
        /// </summary>
        /// <param name="il">事务隔离级别</param>
        private void Init(IsolationLevel il)
        {
            _il = il;
            _dbDatabaseProvider = DatabaseProviderFactory.CreateDatabaseProvider(_dbType);

            //开始缓存数据结构,并初始化dbset
            _typeDescriptors = TypeDescriptors.GetTypeDescriptors(this);
            //this._internalAdoSession = await InternalAdoSession.CreateAsync(_dbDatabaseProvider, _dbConnectionStr);
            //初始化数据链接
            InitDb(isSelect);



            if (_il != IsolationLevel.Unspecified)
            {
                //初始化数据库结构
                InternalAdoSession.BeginTransaction(_il);
            }
        }

        /// <summary>
        /// 创建实体查询对象
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <returns>查询对象</returns>
        public virtual IQuery<TEntity> Query<TEntity>()
        {
            return Query<TEntity>(null);
        }
        /// <summary>
        /// 创建指定表的实体查询对象
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <param name="table">表名</param>
        /// <returns>查询对象</returns>
        public virtual IQuery<TEntity> Query<TEntity>(string table)
        {
            return new Query<TEntity>(this, table);
        }

        /// <summary>
        /// 获取数据库提供程序
        /// </summary>
        internal IDatabaseProvider DatabaseProvider
        {
            get
            {
                CheckDisposed();
                return _dbDatabaseProvider;
            }
        }


        /// <summary>
        /// 获取内部ADO会话实例
        /// </summary>
        internal InternalAdoSession InternalAdoSession
        {
            get
            {
                CheckDisposed();
                //如果为空,就去初始化工厂进行初始化
                _internalAdoSession ??= new InternalAdoSession(_dbDatabaseProvider, _dbConnectionStr);
                return _internalAdoSession;
            }
        }
        /// <summary>
        /// 异步释放上下文使用的非托管资源
        /// </summary>
        /// <returns>表示异步释放操作的任务</returns>
        public async ValueTask DisposeAsync()
        {
            if (!_disposed)
            {
                if (_internalAdoSession != null)
                {
                    await _internalAdoSession.DisposeAsync().ConfigureAwait(false);
                }

                _disposed = true;
            }
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放DbContext使用的所有非托管资源
        /// </summary>
        public void Dispose()
        {
            _internalAdoSession?.Dispose();
            _disposed = true;
            GC.SuppressFinalize(this);
        }
        /// <summary>
        /// 设置数据库命令超时时间
        /// </summary>
        /// <param name="time">超时时间（秒）</param>
        public void SetCommandTimeout(int time)
        {
            InternalAdoSession.CommandTimeout = time;
        }
        /// <summary>
        /// 执行非查询SQL命令（内部重载，默认CommandType.Text）
        /// </summary>
        /// <param name="cmdText">SQL命令文本</param>
        /// <param name="parameters">SQL参数</param>
        /// <returns>受影响的行数</returns>
        internal int ExecuteNoQuery(string cmdText, params DbParam[] parameters)
        {
            return ExecuteNoQuery(cmdText, CommandType.Text, parameters);
        }
        internal async Task<int> ExecuteNoQueryAsync(string cmdText, params DbParam[] parameters)
        {
            return await ExecuteNoQueryAsync(cmdText, CommandType.Text, parameters);
        }
        /// <inheritdoc/>
        public int ExecuteNoQuery(Func<string, string> func, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            return ExecuteNoQuery(cmdText, CommandType.Text, parameters);
        }

        internal int ExecuteNoQuery(string cmdText, CommandType cmdType, params DbParam[] parameters)
        {
            Checks.NotNull(cmdText, nameof(cmdText));
            return InternalAdoSession.ExecuteNonQuery(cmdText, parameters, cmdType);
        }
        internal async Task<int> ExecuteNoQueryAsync(string cmdText, CommandType cmdType, params DbParam[] parameters)
        {
            Checks.NotNull(cmdText, nameof(cmdText));
            return await InternalAdoSession.ExecuteNonQueryAsync(cmdText, parameters, cmdType);
        }
        /// <inheritdoc/>
        public int ExecuteNoQuery(Func<string, string> func, CommandType cmdType, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return InternalAdoSession.ExecuteNonQuery(cmdText, parameters, cmdType);
        }
        /// <summary>
        /// 执行SQL命令并返回数据读取器（内部重载，默认CommandType.Text）
        /// </summary>
        /// <param name="cmdText">SQL命令文本</param>
        /// <param name="parameters">SQL参数</param>
        /// <returns>数据读取器</returns>
        internal IDataReader ExecuteReader(string cmdText, params DbParam[] parameters)
        {
            return ExecuteReader(cmdText, CommandType.Text, parameters);
        }
        /// <inheritdoc/>
        public IDataReader ExecuteReader(Func<string, string> func, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return ExecuteReader(cmdText, CommandType.Text, parameters);
        }
        /// <inheritdoc/>
        internal IDataReader ExecuteReader(string cmdText, CommandType cmdType, params DbParam[] parameters)
        {
            Checks.NotNull(cmdText, nameof(cmdText));
            return InternalAdoSession.ExecuteReader(cmdText, parameters, cmdType);
        }
        /// <inheritdoc/>
        public IDataReader ExecuteReader(Func<string, string> func, CommandType cmdType, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return InternalAdoSession.ExecuteReader(cmdText, parameters, cmdType);
        }

        /// <summary>
        /// 执行SQL命令并返回第一行第一列的值（内部重载，默认CommandType.Text）
        /// </summary>
        /// <param name="cmdText">SQL命令文本</param>
        /// <param name="parameters">SQL参数</param>
        /// <returns>查询结果的第一行第一列</returns>
        internal object ExecuteScalar(string cmdText, params DbParam[] parameters)
        {
            return ExecuteScalar(cmdText, CommandType.Text, parameters);
        }
        /// <inheritdoc/>
        public object ExecuteScalar(Func<string, string> func, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return ExecuteScalar(cmdText, CommandType.Text, parameters);
        }

        internal object ExecuteScalar(string cmdText, CommandType cmdType, params DbParam[] parameters)
        {
            Checks.NotNull(cmdText, nameof(cmdText));
            return InternalAdoSession.ExecuteScalar(cmdText, parameters, cmdType);
        }
        /// <inheritdoc/>
        public object ExecuteScalar(Func<string, string> func, CommandType cmdType, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return InternalAdoSession.ExecuteScalar(cmdText, parameters, cmdType);
        }
        /// <summary>
        /// 执行SQL命令并返回DataTable
        /// </summary>
        /// <param name="cmdText">SQL命令文本</param>
        /// <param name="parameters">SQL参数</param>
        /// <returns>包含查询结果的DataTable</returns>
        internal DataTable ExecuteDataTable(string cmdText, params DbParam[] parameters)
        {
            return ExecuteDataTable(cmdText, CommandType.Text, parameters);
        }
        /// <inheritdoc/>
        public DataTable ExecuteDataTable(Func<string, string> func, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return ExecuteDataTable(cmdText, CommandType.Text, parameters);
        }
        /// <inheritdoc/>
        public DataTable ExecuteDataTable(Func<string, string> func, CommandType cmdType, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return ExecuteDataTable(cmdText, CommandType.Text, parameters);
        }
        internal DataTable ExecuteDataTable(string cmdText, CommandType cmdType, params DbParam[] parameters)
        {
            using IDataReader reader = ExecuteReader(cmdText, cmdType, parameters);
            DataTable dt = new();
            // 使用 TryAdd 方法手动填充 DataTable，避免使用带有 RequiresUnreferencedCodeAttribute 的 Load 方法
            dt.BeginLoadData();
            try
            {
                // 手动填充 DataTable，避免使用带有 RequiresUnreferencedCodeAttribute 的 Load 方法
                dt.Columns.Clear();
                // 添加列
                for (int i = 0; i < reader.FieldCount; i++)
                {
                    _ = dt.Columns.Add(reader.GetName(i), reader.GetFieldType(i));
                }
                // 添加行
                while (reader.Read())
                {
                    DataRow row = dt.NewRow();
                    for (int i = 0; i < reader.FieldCount; i++)
                    {
                        row[i] = reader[i];
                    }
                    dt.Rows.Add(row);
                }
            }
            finally
            {
                dt.EndLoadData();
            }
            return dt;
        }


        /// <summary>
        /// 执行SQL命令并返回实体列表（内部重载，默认CommandType.Text）
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="cmdText">SQL命令文本</param>
        /// <param name="parameters">SQL参数</param>
        /// <returns>实体列表</returns>
        internal IEnumerable<T> ExecuteSqlToList<T>(string cmdText, params DbParam[] parameters)
        {
            return ExecuteSqlToList<T>(cmdText, CommandType.Text, parameters);
        }
        /// <summary>
        /// 执行SQL命令并返回实体列表（根据数据库类型生成命令文本）
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="func">根据数据库类型生成SQL命令的委托</param>
        /// <param name="parameters">SQL参数</param>
        /// <returns>实体列表</returns>
        public IEnumerable<T> ExecuteSqlToList<T>(Func<string, string> func, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return ExecuteSqlToList<T>(cmdText, CommandType.Text, parameters);
        }

        /// <summary>
        /// 执行SQL命令并返回实体列表（内部重载，指定CommandType）
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="cmdText">SQL命令文本</param>
        /// <param name="cmdType">命令类型</param>
        /// <param name="parameters">SQL参数</param>
        /// <returns>实体列表</returns>
        internal IEnumerable<T> ExecuteSqlToList<T>(string cmdText, CommandType cmdType, params DbParam[] parameters)
        {
            Checks.NotNull(cmdText, nameof(cmdText));
            return new InternalSqlQuery<T>(this, cmdText, cmdType, parameters);
        }
        /// <summary>
        /// 执行SQL命令并返回实体列表（根据数据库类型生成命令文本，指定CommandType）
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="func">根据数据库类型生成SQL命令的委托</param>
        /// <param name="cmdType">命令类型</param>
        /// <param name="parameters">SQL参数</param>
        /// <returns>实体列表</returns>
        public IEnumerable<T> ExecuteSqlToList<T>(Func<string, string> func, CommandType cmdType, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return new InternalSqlQuery<T>(this, cmdText, cmdType, parameters);
        }

        /// <summary>
        /// 开始数据库事务
        /// </summary>
        public void BeginTran()
        {
            //初始化数据库结构
            InternalAdoSession.BeginTransaction();
        }
        /// <summary>
        /// 异步开始数据库事务
        /// </summary>
        /// <returns></returns>
        public async Task BeginTranAsync()
        {
            //初始化数据库结构
            await InternalAdoSession.BeginTransactionAsync();
        }

        /// <summary>
        /// 开始数据库事务并指定隔离级别
        /// </summary>
        /// <param name="il">事务隔离级别</param>
        public void BeginTran(IsolationLevel? il)
        {
            if (il.HasValue)
            {
                //初始化数据库结构
                InternalAdoSession.BeginTransaction(il);
            }
            else
            {
                //初始化数据库结构
                InternalAdoSession.BeginTransaction(_il);
            }
        }
        /// <summary>
        /// 异步开始数据库事务并指定隔离级别
        /// </summary>
        /// <param name="il">事务隔离级别</param>
        /// <returns></returns>
        public async Task BeginTranAsync(IsolationLevel? il)
        {
            if (il.HasValue)
            {
                //初始化数据库结构
                await InternalAdoSession.BeginTransactionAsync(il);
            }
            else
            {
                //初始化数据库结构
                await InternalAdoSession.BeginTransactionAsync(_il);
            }
        }

        /// <summary>
        /// 回滚当前事务
        /// </summary>
        public void Rollback()
        {
            InternalAdoSession.RollbackTransaction();
        }
        /// <summary>
        /// 异步回滚当前事务
        /// </summary>

        public async Task RollbackAsync()
        {
            await InternalAdoSession.RollbackTransactionAsync();
        }

        /// <summary>
        /// 提交当前事务并开始新事务
        /// </summary>
        public void Save()
        {
            InternalAdoSession.CommitTransaction();
            //初始化数据库结构
            InternalAdoSession.BeginTransaction(_il);
        }
        /// <summary>
        /// 异步提交当前事务并开始新事务
        /// </summary>

        public async Task SaveAsync()
        {
            await InternalAdoSession.CommitTransactionAsync();
            //初始化数据库结构
            await InternalAdoSession.BeginTransactionAsync(_il);
        }

        /// <summary>
        /// 检查当前实例是否已释放
        /// </summary>
        /// <exception cref="ObjectDisposedException">当实例已释放时抛出</exception>
        private void CheckDisposed()
        {
            ObjectDisposedException.ThrowIf(_disposed, this);
        }
        /// <summary>
        /// 添加数据库命令拦截器
        /// </summary>
        /// <param name="interceptor">命令拦截器实例</param>
        protected abstract void AddInterceptor(DbCommandInterceptor interceptor);

        /// <summary>
        /// 移除数据库命令拦截器
        /// </summary>
        /// <param name="interceptor">命令拦截器实例</param>
        protected abstract void RemoveInterceptor(DbCommandInterceptor interceptor);



        /// <summary>
        /// 异步执行SQL命令并返回第一行第一列的值
        /// </summary>
        /// <param name="func">根据数据库类型生成SQL命令的委托</param>
        /// <param name="parameters">SQL命令参数</param>
        /// <returns>查询结果的第一行第一列</returns>
        public async Task<object> ExecuteScalarAsync(Func<string, string> func, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return await InternalAdoSession.ExecuteScalarAsync(cmdText, parameters, CommandType.Text).ConfigureAwait(false);
        }

        /// <summary>
        /// 异步执行SQL命令并返回第一行第一列的值
        /// </summary>
        /// <param name="func">根据数据库类型生成SQL命令的委托</param>
        /// <param name="cmdType">命令类型</param>
        /// <param name="parameters">SQL命令参数</param>
        /// <returns>查询结果的第一行第一列</returns>
        public async Task<object> ExecuteScalarAsync(Func<string, string> func, CommandType cmdType, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return await InternalAdoSession.ExecuteScalarAsync(cmdText, parameters, cmdType).ConfigureAwait(false);
        }

        /// <summary>
        /// 异步执行SQL命令并返回数据读取器
        /// </summary>
        /// <param name="func">根据数据库类型生成SQL命令的委托</param>
        /// <param name="parameters">SQL命令参数</param>
        /// <returns>数据读取器</returns>
        public async Task<IDataReader> ExecuteReaderAsync(Func<string, string> func, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return await InternalAdoSession.ExecuteReaderAsync(cmdText, parameters, CommandType.Text).ConfigureAwait(false);
        }

        /// <summary>
        /// 异步执行SQL命令并返回数据读取器
        /// </summary>
        /// <param name="func">根据数据库类型生成SQL命令的委托</param>
        /// <param name="cmdType">命令类型</param>
        /// <param name="parameters">SQL命令参数</param>
        /// <returns>数据读取器</returns>
        public async Task<IDataReader> ExecuteReaderAsync(Func<string, string> func, CommandType cmdType, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return await InternalAdoSession.ExecuteReaderAsync(cmdText, parameters, cmdType).ConfigureAwait(false);
        }

        /// <summary>
        /// 异步执行SQL命令并返回数据表
        /// </summary>
        /// <param name="func">根据数据库类型生成SQL命令的委托</param>
        /// <param name="parameters">SQL命令参数</param>
        /// <returns>包含查询结果的数据表</returns>
        public async Task<DataTable> ExecuteDataTableAsync(Func<string, string> func, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            using IDataReader reader = await InternalAdoSession.ExecuteReaderAsync(cmdText, parameters, CommandType.Text).ConfigureAwait(false);
            DataTable dt = new();
            // 使用 TryAdd 方法手动填充 DataTable，避免使用带有 RequiresUnreferencedCodeAttribute 的 Load 方法
            dt.BeginLoadData();
            try
            {
                // 手动填充 DataTable，避免使用带有 RequiresUnreferencedCodeAttribute 的 Load 方法
                dt.Columns.Clear();
                // 添加列
                for (int i = 0; i < reader.FieldCount; i++)
                {
                    _ = dt.Columns.Add(reader.GetName(i), reader.GetFieldType(i));
                }
                // 添加行
                while (reader.Read())
                {
                    DataRow row = dt.NewRow();
                    for (int i = 0; i < reader.FieldCount; i++)
                    {
                        row[i] = reader[i];
                    }
                    dt.Rows.Add(row);
                }
            }
            finally
            {
                dt.EndLoadData();
            }
            return dt;
        }

        /// <summary>
        /// 异步执行SQL命令并返回数据表
        /// </summary>
        /// <param name="func">根据数据库类型生成SQL命令的委托</param>
        /// <param name="cmdType">命令类型</param>
        /// <param name="parameters">SQL命令参数</param>
        /// <returns>包含查询结果的数据表</returns>
        public async Task<DataTable> ExecuteDataTableAsync(Func<string, string> func, CommandType cmdType, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            using IDataReader reader = await InternalAdoSession.ExecuteReaderAsync(cmdText, parameters, cmdType).ConfigureAwait(false);
            DataTable dt = new();
            // 使用 TryAdd 方法手动填充 DataTable，避免使用带有 RequiresUnreferencedCodeAttribute 的 Load 方法
            dt.BeginLoadData();
            try
            {
                // 手动填充 DataTable，避免使用带有 RequiresUnreferencedCodeAttribute 的 Load 方法
                dt.Columns.Clear();
                // 添加列
                for (int i = 0; i < reader.FieldCount; i++)
                {
                    _ = dt.Columns.Add(reader.GetName(i), reader.GetFieldType(i));
                }
                // 添加行
                while (reader.Read())
                {
                    DataRow row = dt.NewRow();
                    for (int i = 0; i < reader.FieldCount; i++)
                    {
                        row[i] = reader[i];
                    }
                    dt.Rows.Add(row);
                }
            }
            finally
            {
                dt.EndLoadData();
            }
            return dt;
        }

        /// <summary>
        /// 异步执行非查询SQL命令
        /// </summary>
        /// <param name="func">根据数据库类型生成SQL命令的委托</param>
        /// <param name="parameters">SQL命令参数</param>
        /// <returns>受影响的行数</returns>
        public async Task<int> ExecuteNoQueryAsync(Func<string, string> func, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return await InternalAdoSession.ExecuteNonQueryAsync(cmdText, parameters, CommandType.Text).ConfigureAwait(false);
        }

        /// <summary>
        /// 异步执行非查询SQL命令
        /// </summary>
        /// <param name="func">根据数据库类型生成SQL命令的委托</param>
        /// <param name="cmdType">命令类型</param>
        /// <param name="parameters">SQL命令参数</param>
        /// <returns>受影响的行数</returns>
        public async Task<int> ExecuteNoQueryAsync(Func<string, string> func, CommandType cmdType, params DbParam[] parameters)
        {
            string cmdText = func(_dbDatabaseProvider.DatabaseType);
            Checks.NotNull(cmdText, "cmdText");
            return await InternalAdoSession.ExecuteNonQueryAsync(cmdText, parameters, cmdType).ConfigureAwait(false);
        }

        /// <summary>
        /// 获取或设置数据库升级记录集合
        /// </summary>
        public DbSet<SZORM_Upgrade> SZORM_Upgrades { get; set; }
    }
    /// <summary>
    /// 数据库升级记录实体类
    /// </summary>
    public class SZORM_Upgrade
    {
        /// <summary>
        /// 升级版本号
        /// </summary>
        public int? Version { get; set; }
        /// <summary>
        /// 升级内容描述
        /// </summary>
        [SZColumn(MaxLength = 4000)]
        public string UPContent { get; set; }
        /// <summary>
        /// 升级执行时间
        /// </summary>
        public DateTime? UPTime { get; set; }
        /// <summary>
        /// 版本发布时间
        /// </summary>
        /// <summary>
        /// 版本发布时间
        /// </summary>
        public DateTime? ReleaseTime { get; set; }
        /// <summary>
        /// 升级错误信息
        /// </summary>
        [SZColumn(MaxLength = 4000)]
        public string ErrorMsg { get; set; }
    }
}
